package com.weiyi.portal.controller;


import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.weiyi.portal.config.WebSocketConfig;
import com.weiyi.portal.modules.ums.model.UmsChatMessage;
import com.weiyi.portal.modules.ums.service.ChatService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.core.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@ServerEndpoint(value = "/websocket/{username}",configurator= WebSocketConfig.class)
@Api(tags = "Sokcet聊天Controller", description = "聊天功能")
@Component
public class WebSocket {

    //用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>();
    //用来记录username和该session进行绑定
    private static Map<String, Session> map = new HashMap<String, Session>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    //用户名
    private String username;

    private ApplicationContext applicationContext;
    //聊天逻辑层service
    private ChatService chatService;


    /**
     * 连接建立成功调用的方法，初始化昵称、session
     */
    @OnOpen
    public void onOpen(@PathParam("username")String username, Session session, EndpointConfig config) {


        //获取登录时存放httpSession的用户数据
        HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        //必须手动注入依赖，因为Springboot是单例模式，而websocket是多例模式，AOP不能用了
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(httpSession.getServletContext());

        //User user = (User) httpSession.getAttribute("user");
        //UmsMember user = (UmsMember) httpSession.getAttribute("user");

        //获取全局容器
        this.session = session;
        this.username = username;
        this.chatService = (ChatService) applicationContext.getBean("chatService");

        //绑定username与session
        map.put(username, session);

        webSocketSet.add(this);     //加入set中

    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {

        //断开连接，重置窗口值
        //chatService.resetWindows(username);

        webSocketSet.remove(this);  //从set中删除
        map.remove(this.username);
        System.out.println("111");

    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) {

        //从客户端传过来的数据是json数据，所以这里使用jackson进行转换为chatMsg对象，
        ObjectMapper objectMapper = new ObjectMapper();
        UmsChatMessage chatMsg;

        try {
            chatMsg = objectMapper.readValue(message, UmsChatMessage.class);

            //对chatMsg进行装箱
            chatMsg.setFromUser(username);
            chatMsg.setSendTime(new Date());
            chatMsg.setIsLatest(1);
            chatMsg.setMessageId(null);

            Session fromSession = map.get(chatMsg.getFromUser());
            Session toSession = map.get(chatMsg.getToUser());

            //发送给接收者.
            fromSession.getAsyncRemote().sendText(username + "：" + chatMsg.getContent());

            if (toSession != null) {
                //发送给发送者.
                toSession.getAsyncRemote().sendText(username + "：" + chatMsg.getContent());
            }

            //判断两者是否第一次聊天，进行关系表、聊天列表、空白信息的初始化
            chatService.isFirstChat(chatMsg.getFromUser(), chatMsg.getToUser());

            //查询聊天两者的联系id
            String linkId = chatService.selectAssociation(username, chatMsg.getToUser());

            chatMsg.setLinkId(linkId);

            //保存聊天记录信息
            chatService.saveMessage(chatMsg);

        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 群发自定义消息
     */
    public void broadcast(String message) {
        for (WebSocket item : webSocketSet) {

            //异步发送消息.
            item.session.getAsyncRemote().sendText(message);
        }
    }
}

